package dht.threads;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.ArrayList;

import dht.communication.PortThread;
import dht.interfaceThread.InterMajVoisins;
import dht.message.MajMessage;
import dht.message.Message;
import dht.message.exception.ErrorMessage;
import dht.node.Node;
import dht.tools.Couple;

/**
 * Thread qui receptionne des mises a jour des voisins.
 * @author bouceka
 *
 */
public class ManageMajVoisins extends Thread implements InterMajVoisins{

	private DatagramSocket socketReceiveMajVoisin = null;
	private Message msgRecu = null;

	public ManageMajVoisins(){

		try {
			this.socketReceiveMajVoisin= new DatagramSocket(PortThread.PORT_RECEIVE_MAJ);
		} catch (SocketException e) {
			e.printStackTrace();
		} 

	}

	public void receiveMajVoisins() throws ErrorMessage {

		DatagramPacket in = null;
		byte[] buff = null;
		ByteArrayInputStream monStream = null;
		ObjectInputStream ois = null;
		int dim = -1;

		buff = new byte[65536];
		in  = new DatagramPacket(buff,65536);

		System.out.println("Thread ManageMajVoisins : Attente requete MAJ...");
		try {
			this.socketReceiveMajVoisin.receive(in); // Attente d'une requete
		} catch (IOException e) {
			e.printStackTrace();
		}

		monStream = new ByteArrayInputStream(buff);
		
		try {
			ois = new ObjectInputStream(monStream);
			msgRecu = (Message)ois.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

		if(this.msgRecu.TYPE_MSG == Message.MAJ_Message){
			
			MajMessage mm = (MajMessage)this.msgRecu;
			
			/*
			 * dim correspond a la dimension sur laquelle est le nouveau voisin.
			 * On doit mettre a jour la liste courante dans la direction oppose 
			 * au nouveau noeud afin qu'il soit un voisin d'ou le traitement
			 * sur dim.
			 */
			dim = (mm.getDim()%2 == 0) ? mm.getDim() + 1 : mm.getDim() - 1;

			synchronized(Node.myContext){
				
				System.out.println("dim :" +dim+ " "+Node.myContext.getVoisinage().size());
				
				ArrayList<Couple<String>> liste = Node.myContext.getVoisinage().get(dim);
				
				Couple<String> newCouple = new Couple<String>(mm.getVirtualId(),mm.getadresseIpExp().toString().substring(1));
				
				if(liste == null){
					Node.myContext.getVoisinage().set(dim, new ArrayList<Couple<String>>());
					Node.myContext.getVoisinage().get(dim).add(newCouple);
					System.out.println(Node.myContext);
					return;
				}

				liste.add(newCouple);
				System.out.println(Node.myContext);
			}
		}
		else{
			throw new ErrorMessage();
		}
		
		return;
	}

	public void run() {

		while(true){ // Boucle de reception des MAJ

			try {
				this.receiveMajVoisins();
			} catch (ErrorMessage e) {
				e.printStackTrace();
			}
		}
	}

}
